<template>
  <el-upload
    ref="uploadFileRef"
    name="file"
    class="w-full"
    :drag="drag"
    :class="!drag ? 'file-uploader' : ''"
    :action="uploadUrl"
    :headers="headers"
    :show-file-list="true"
    :on-error="handleError"
    :on-success="handleSuccess"
    :on-progress="handleOnProgress"
    :before-upload="beforeUpload"
  >
    <div v-if="!drag" :style="iconStyle">
      <i :class="iconClass" class="wh-14px color-info mt-2px"></i>
    </div>
    <div v-else>
      <i class="i-ep-upload color-info"></i>
      <p class="color-info">将文件拖到此处，或点击此处选择文件</p>
    </div>
    <!--    accept=".jpg,.jpeg,.png,.gif,.bmp,.pdf,.JPG,.JPEG,.PBG,.GIF,.BMP,.PDF"-->
  </el-upload>
</template>

<script setup lang="ts">
  import type { UploadProps } from 'element-plus'

  import type { CSSProperties } from 'vue'

  import { getToken } from '#/utils/auth'
  import { ElMessage } from 'element-plus'

  defineOptions({
    name: 'UploadFile',
  })

  const props = withDefaults(
    defineProps<{
      drag?: boolean
      field: string // 字段名
      height?: number
      isCreate: boolean
      preview: string
      targetField?: string
      upload: string
      width?: number
    }>(),
    {
      width: 320,
      height: 320,
      targetField: 'file_name', // 要填充的目标表单控件名称
      drag: true,
    }
  )

  const emits = defineEmits<{
    (e: 'on-uploaded', targetField: string, data: string): void
    (e: 'update:modelValue', path: string): void
  }>()
  const uploadFileRef = ref()
  const headers = ref({ Authorization: `Bearer ${getToken()}` })
  const fileUrl = ref('')
  const uploading = ref(false)

  const uploadUrl = computed(() => import.meta.env.VITE_APP_BASE_API + props.upload)
  const iconClass = computed(() => (uploading.value ? 'i-ep-loading' : 'i-ep-plus'))
  const iconStyle = computed<CSSProperties>(() => {
    return { height: '300px', width: '36px', lineHeight: '36px', textAlign: 'center' }
  })

  watch(
    () => props.preview,
    (newV, oldV) => {
      // console.log('UploadFile watch [preview] newV: ' + newV + ', oldV: ' + oldV)
      fileUrl.value = props.isCreate ? '' : (newV ?? '')
    },
    {
      immediate: true,
    }
  )

  const handleOnProgress: UploadProps['onProgress'] = (res, file) => {
    uploading.value = true
  }
  const handleError: UploadProps['onError'] = (err, file) => {
    let msg = ''

    switch (err.status) {
      case 403: {
        msg = '没有权限进行该操作。'

        break
      }
      case 413: {
        msg = '文件太大，先压缩文件体积再尝试。'

        break
      }
      case 522: {
        msg = JSON.parse(err.message)
        msg = msg.message

        break
      }
      default: {
        err = JSON.parse(err.message)
        msg = err.errors[props.field][0]
      }
    }

    ElMessage({ message: msg, type: 'error' })
    uploading.value = false
  }
  const handleSuccess: UploadProps['onSuccess'] = (res, file) => {
    uploading.value = false
    fileUrl.value = res.data.url

    emits('on-uploaded', props.targetField, res.data.file_name)
    emits('update:modelValue', res.data.file_path)
  }

  const beforeUpload: UploadProps['beforeUpload'] = (file) => {
    // audio/x-m4a
    // const types = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'audio/mpeg', 'video/mp4',
    //                'application/pdf',
    //                'text/markdown',
    //                'application/zip',
    //                'application/vnd.openxmlformats-officedocument.presentationml.presentation', // pptx
    //                'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // docx
    //                'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' // xlsx
    // ]

    const isLimit = file.size / 1024 / 1024 < 200
    if (!isLimit) {
      ElMessage({ message: '上传文件大小不能超过 200MB', type: 'error' })
      fileUrl.value = props.preview === '' ? '' : props.preview
      return false
    }

    // if (imgTypes.indexOf(file.raw.type) === -1) {
    // if (types.indexOf(file.type) === -1) {
    //     this.$message.error('仅支持 jpg, jpeg, png, gif, mp3, mp4, docx, xlsx, pptx, txt, md 格式')
    //     return false
    // }

    return true
  }

  const resetData = () => {
    uploadFileRef.value?.clearFiles()
    fileUrl.value = ''
  }

  defineExpose({
    resetData,
  })
</script>

<style lang="scss" scoped>
  .file-uploader {
    @apply mb-1px;
  }

  .file-uploader .el-upload {
    position: relative;
    overflow: hidden;
    border: 1px dashed var(--text-color-place);
    border-radius: 6px;
  }

  .file-uploader .el-upload:hover {
    border-color: var(--primary-color);

    .color-info {
      color: var(--primary-color);
    }
  }
</style>
